using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.Text;
using System.Data;

using Microsoft.SharePoint;

namespace ProjectCompliance.WebParts
{
    class Util
    {

        // Properties of the site (web).  These simple routines are declared here to
        // entralize potential changes to their implementation, such as replacing 
        // the storage of values with a list instead of the web's property bag.

        internal static void EnsureSiteProperties(SPWeb web)
        {

            if (!web.Properties.ContainsKey("SiteType"))
                web.Properties.Add("SiteType", "");
            if (!web.Properties.ContainsKey("ProjectStatus"))
                web.Properties.Add("ProjectStatus", "");
            if (!web.Properties.ContainsKey("ProjectStatusComment"))
                web.Properties.Add("ProjectStatusComment", "");
            if (!web.Properties.ContainsKey("FinalAuditNumber"))
                web.Properties.Add("FinalAuditNumber", "0");
            if (!web.Properties.ContainsKey("InitialAuditNumber"))
                web.Properties.Add("InitialAuditNumber", "0");
            if (!web.Properties.ContainsKey("FinalAuditComment"))
                web.Properties.Add("FinalAuditComment", "0");
            if (!web.Properties.ContainsKey("InitialAuditComment"))
                web.Properties.Add("InitialAuditComment", "0");
            web.Update();
        }

        internal static string GetSiteType(SPWeb web)
        {
            EnsureSiteProperties(web);
            return web.Properties["SiteType"];
        }

        /// <summary>
        /// Record type of site to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="SiteType"></param>
        internal static void SetSiteType(SPWeb web, string SiteType)
        {
            EnsureSiteProperties(web);
            web.Properties["SiteType"] = SiteType;
        }

        internal static string GetProjectStatus(SPWeb web)
        {
            EnsureSiteProperties(web);
            return web.Properties["ProjectStatus"];
        }

        /// <summary>
        /// Record status of project to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="ProjectStatus"></param>
        internal static void SetProjectStatus(SPWeb web, string ProjectStatus)
        {
            EnsureSiteProperties(web);
            web.Properties["ProjectStatus"] = ProjectStatus;
        }

        internal static string GetProjectStatusComment(SPWeb web)
        {
            EnsureSiteProperties(web);
            return web.Properties["ProjectStatusComment"];
        }

        /// <summary>
        /// Record comment for project to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="ProjectStatusComment"></param>
        internal static void SetProjectStatusComment(SPWeb web, string ProjectStatusComment)
        {
            EnsureSiteProperties(web);
            web.Properties["ProjectStatusComment"] = ProjectStatusComment;
        }

        internal static int GetFinalAuditNumber(SPWeb web)
        {
            EnsureSiteProperties(web);
            return Convert.ToInt32(web.Properties["FinalAuditNumber"]);
        }

        /// <summary>
        /// Record final audit number to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="FinalAuditNumber"></param>
        internal static void SetFinalAuditNumber(SPWeb web, int FinalAuditNumber)
        {
            EnsureSiteProperties(web);
            web.Properties["FinalAuditNumber"] = FinalAuditNumber.ToString();
        }

        internal static string GetFinalAuditComment(SPWeb web)
        {
            EnsureSiteProperties(web);
            return web.Properties["FinalAuditComment"];
        }

        /// <summary>
        /// Record final audit comment to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="FinalAuditNumber"></param>
        internal static void SetFinalAuditComment(SPWeb web, string FinalAuditComment)
        {
            EnsureSiteProperties(web);
            web.Properties["FinalAuditComment"] = FinalAuditComment;
        }

        internal static int GetInitialAuditNumber(SPWeb web)
        {
            EnsureSiteProperties(web);
            return Convert.ToInt32(web.Properties["InitialAuditNumber"]);
        }

        /// <summary>
        /// Record Initial audit number to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="InitialAuditNumber"></param>
        internal static void SetInitialAuditNumber(SPWeb web, int InitialAuditNumber)
        {
            EnsureSiteProperties(web);
            web.Properties["InitialAuditNumber"] = InitialAuditNumber.ToString();
        }

        internal static string GetInitialAuditComment(SPWeb web)
        {
            EnsureSiteProperties(web);
            return web.Properties["InitialAuditComment"];
        }

        /// <summary>
        /// Record Initial audit comment to web; be sure to use web.Properties.Update() to commit.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="InitialAuditComment"></param>
        internal static void SetInitialAuditComment(SPWeb web, string InitialAuditComment)
        {
            EnsureSiteProperties(web);
            web.Properties["InitialAuditComment"] = InitialAuditComment;
        }

        internal static void SetButtonStyle(ref Button btn)
        {
            btn.Attributes.Add("class", "ms-menutoolbar");
            btn.Attributes.Add("onmouseover", "this.className='ms-splitbuttonhover'");
            btn.Attributes.Add("onmouseout", "this.className='ms-menutoolbar'");
            btn.Style.Add("cursor", "hand");
            // The following elements seem to change between the hover styles, so we lock them here
            btn.Style.Add("height", "18pt");
            btn.Style.Add("border-width", "thin");
            btn.Style.Add("margin", "1px");
        }

        /// <summary>
        /// Return value of field in DataRow as a string; treat nulls as empty strings.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static string GetString(DataRow row, string fieldName)
        {
            return GetString(row, fieldName, DataRowVersion.Current);
        }

        /// <summary>
        /// Return value of field in DataRow as a string; treat nulls as empty strings.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static string GetString(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            string result = "";

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                result = (string)dbFieldValue;

            return result;
        }


        /// <summary>
        /// Return value of field in DataRow as a DateTime; treat nulls as empty strings.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static DateTime GetDateTime(DataRow row, string fieldName)
        {
            return GetDateTime(row, fieldName, DataRowVersion.Current);
        }

        /// <summary>
        /// Return value of field in DataRow as a DateTime; treat nulls as empty strings.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static DateTime GetDateTime(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            DateTime result = DateTime.MinValue;

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                result = (DateTime)dbFieldValue;

            return result;
        }


        /// <summary>
        /// Return value of field in DataRow as an int; treat nulls as zero.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static int GetInt(DataRow row, string fieldName)
        {
            return GetInt(row, fieldName, DataRowVersion.Current);
        }


        /// <summary>
        /// Return value of field in DataRow as an int; treat nulls as zero.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static int GetInt(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            int result = 0;

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                result = (int)dbFieldValue;

            return result;
        }


        /// <summary>
        /// Return value of field in DataRow as a GUID; treat nulls as Guid.Empty
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static Guid GetGuid(DataRow row, string fieldName)
        {
            return GetGuid(row, fieldName, DataRowVersion.Current);
        }


        /// <summary>
        /// Return value of field in DataRow as an int; treat nulls as Guid.Empty.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static Guid GetGuid(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            Guid result = Guid.Empty;

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                //result = (Guid)dbFieldValue;
                result = new Guid((string)dbFieldValue);

            return result;
        }


        /// <summary>
        /// Return value of field in DataRow as an object.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static Object GetObject(DataRow row, string fieldName)
        {
            return GetObject(row, fieldName, DataRowVersion.Current);
        }


        /// <summary>
        /// Return value of field in DataRow as an object.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static Object GetObject(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            Object result = null;

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                result = (Object)dbFieldValue;

            return result;
        }


        /// <summary>
        /// Return value of field in DataRow as double; treat nulls as zero.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <returns></returns>
        internal static double GetDouble(DataRow row, string fieldName)
        {
            return GetDouble(row, fieldName, DataRowVersion.Current);
        }

        /// <summary>
        /// Return value of field in DataRow as double; treat nulls as zero.
        /// </summary>
        /// <param name="row">Row from DataTable</param>
        /// <param name="fieldName">Name of field to return</param>
        /// <param name="version">DataRowVersion (Current, Default, Original, Proposed).  Use Original to get information from deleted rows.</param>
        /// <returns></returns>
        internal static double GetDouble(DataRow row, string fieldName, DataRowVersion version)
        {
            object dbFieldValue = null;
            double result = 0.0;

            dbFieldValue = row[fieldName, version];
            if ((!(dbFieldValue is System.DBNull)) &&
                 (!(dbFieldValue == null)))
                result = (double)dbFieldValue;

            return result;
        }


        /// <summary>
        /// Get a ContentTypeId from its name
        /// </summary>
        /// <param name="ContentTypeName"></param>
        /// <returns></returns>
        internal static SPContentTypeId GetContentTypeId(SPWeb web, string ContentTypeName)
        {
            SPContentTypeCollection contenttypes;
            SPContentTypeId contenttypeId = SPContentTypeId.Empty;

            try
            {
                contenttypes = web.AvailableContentTypes;
                contenttypeId = contenttypes[ContentTypeName].Id;
            }
            catch (Exception)
            {
                // ContentType was not found; just return empty SPContentTypeId in this case, don't throw exception
            }
            return contenttypeId;
        }


        /// <summary>
        /// Get a list's Guid from its name
        /// </summary>
        /// <param name="ListName"></param>
        /// <returns></returns>
        internal static Guid GetListGuid(SPWeb web, string ListName)
        {
            SPListCollection lists;
            Guid listGuid = Guid.Empty;

            try
            {
                lists = web.Lists;
                listGuid = lists[ListName].ID;
            }
            catch (Exception)
            {
                // List was not found; just return empty GUID in this case, don't throw exception
            }

            return listGuid;
        }


        /// <summary>
        /// Get a list's Guid from its name
        /// </summary>
        /// <param name="ListName"></param>
        /// <returns></returns>
        internal static Guid GetFieldGuid(SPWeb web, string ListName, string FieldName)
        {
            SPList list;
            Guid fieldGuid = Guid.Empty;

            try
            {
                list = web.Lists[ListName];
                fieldGuid = list.Fields[FieldName].Id;
            }
            catch (Exception)
            {
                // Field was not found; just return empty GUID in this case, don't throw exception
            }

            return fieldGuid;
        }


        internal static void LoadRule(DataRow row, ref ComplianceRule Rule)
        {
            string ContenttypeIdString;

            Rule.RuleName = Util.GetString(row, "Title");
            Rule.SetOperator(Util.GetString(row, "ComplianceRuleOperator"));
            Rule.ManualInstructions = Util.GetString(row, "ComplianceManualInstructions");
            Rule.Comments = Util.GetString(row, "ComplianceItemComments");
            Rule.ContentTypeName = Util.GetString(row, "ComplianceContenttypeName");
            Rule.LibraryName = Util.GetString(row, "ComplianceLibraryName");
            Rule.FieldName = Util.GetString(row, "ComplianceFieldName");
            Rule.FieldValue = Util.GetObject(row, "ComplianceFieldValue");
            Rule.SetFieldComparer(Util.GetString(row, "ComplianceFieldComparer"));
            Rule.SetFieldType(Util.GetString(row, "ComplianceFieldType"));
            ContenttypeIdString = Util.GetString(row, "ComplianceContenttypeId");
            if (ContenttypeIdString != "")
                Rule.ContentTypeId = new SPContentTypeId(ContenttypeIdString);
            Rule.LibraryGuid = Util.GetGuid(row, "ComplianceLibraryGUID");
            Rule.FieldGuid = Util.GetGuid(row, "ComplianceFieldGUID");
        }


        /// <summary>
        /// Create a Table object of specified number of rows and columns.  
        /// Use to create tables for web part layouts.
        /// </summary>
        /// <example>
        ///    // Controls in web part:
        ///    Table controlTable;
        ///    Button submitButton;
        ///    TextBox submitValue;
        /// 
        ///    // CreateChildControls() method in web part:
        ///    controlTable = Util.NewHtmlTable(1, 2);
        ///    controlTable.CellPadding = 2;
        ///    this.Controls.Add(controlTable);
        /// 
        ///    submitButton = new Button();
        ///    submitButton.Text = "Perform Audit";
        ///    submitButton.Click += new EventHandler(submitButton_Click);
        ///    controlTable.Rows[0].Cells[0].Controls.Add(submitButton);
        /// 
        ///    submitValue = new TextBox();
        ///    submitValue.ToolTip = "Enter your value here.";
        ///    controlTable.Rows[0].Cells[1].Controls.Add(submitValue);
        /// </example>
        /// <param name="rows"></param>
        /// <param name="cols"></param>
        /// <returns>System.Web.UI.WebControls.Table</returns>
        internal static Table NewHtmlTable(int rows, int cols)
        {
            Table result;
            TableRow row;
            TableCell col;

            result = new Table();
            for (int r = 0; r < rows; r++)
            {
                row = new TableRow();
                for (int c = 0; c < cols; c++)
                {
                    col = new TableCell();
                    col.VerticalAlign = VerticalAlign.Top; // Can reset this later if desired.
                    row.Cells.Add(col);
                }
                result.Rows.Add(row);
            }
            return result;
        }

        internal static int AddHtmlRow(ref Table HtmlTable)
        {
            int cols;
            TableRow row;
            TableCell col;

            row = HtmlTable.Rows[0];
            cols = row.Cells.Count;

            row = new TableRow();
            for (int c = 0; c < cols; c++)
            {
                col = new TableCell();
                col.VerticalAlign = VerticalAlign.Top; // Can reset this later if desired.
                row.Cells.Add(col);
            }
            HtmlTable.Rows.Add(row);

            return HtmlTable.Rows.Count-1;
        }


        /// <summary>
        /// Regular expression to isolate a filename ("$1") or its extension ("$2")
        /// </summary>
        /// <example>
        ///    string Filename, FilenameOnly, FileExtension;
        ///    if (Util.rexFilename.Match(Filename).Success)
        ///    {
        ///        FilenameOnly = Util.rexFilename.Match(Filename).Result("$1");
        ///        FileExtension = Util.rexFilename.Match(Filename).Result("$2");
        ///    }
        /// </example>
        internal static System.Text.RegularExpressions.Regex rexFilename =
        new System.Text.RegularExpressions.Regex(
        @"(.*)\.(.*$)",
        System.Text.RegularExpressions.RegexOptions.Compiled);


        /// <summary>
        /// Regular expression to isolate multi-choice values
        /// </summary>
        /// <example>
        //    System.Text.RegularExpressions.Match choice;
        //    string strField;
        //    foreach (SPListItem item in list.Items)
        //    {
        //        strField = (string)item["MultiChoiceField"];
        //        output.Append(item.Title + ": " + strField + "<BR>");
        //        if (strField != null)
        //        {
        //            choice = Util.rexMultiChoiceField.Match(strField);
        //            while (choice.Success)
        //            {
        //                output.Append("- " + choice.Result("$1") + "<BR>");
        //                choice = choice.NextMatch();
        //            }
        //        }
        //    }
        ///// </example>
        internal static System.Text.RegularExpressions.Regex rexMultiChoiceField =
        new System.Text.RegularExpressions.Regex(
        @"#(.+?);",
        System.Text.RegularExpressions.RegexOptions.Compiled);


        /// <summary>
        /// Regular expression to isolate an ID ("$1") or lookup value ("$2")
        /// </summary>
        /// <example>
        ///    string LookupField, LookupId, LookupValue;
        ///    if (Util.rexLookupField.Match(LookupField).Success)
        ///    {
        ///        LookupId = Util.rexLookupField.Match(LookupField).Result("$1");
        ///        LookupValue = Util.rexLookupField.Match(LookupField).Result("$2");
        ///    }
        /// </example>
        internal static System.Text.RegularExpressions.Regex rexLookupField =
        new System.Text.RegularExpressions.Regex(
        @"(\d+);#(.*)$",
        System.Text.RegularExpressions.RegexOptions.Compiled);


        /// <summary>
        /// Regular expression to isolate a URL ("$1") or its Description ("$2")
        /// </summary>
        /// <example>
        ///    string UrlField, UrlPath, UrlName;
        ///    if (Util.rexUrlField.Match(UrlField).Success)
        ///    {
        ///        UrlPath = Util.rexUrlField.Match(UrlField).Result("$1");
        ///        UrlName = Util.rexUrlField.Match(UrlField).Result("$2");
        ///    }
        /// </example>
        internal static System.Text.RegularExpressions.Regex rexUrlField =
        new System.Text.RegularExpressions.Regex(
        @"^(.*), +(.*)$",
        System.Text.RegularExpressions.RegexOptions.Compiled);



    }
}
